package com.eicas;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.io.DecodingException;
import io.jsonwebtoken.security.Keys;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;

/**
 * JWT token manager.
 *
 * @author wfnuser
 * @author nkorange
 */
@Component
public class JwtTokenManager {
    private static final String AUTHORITIES_KEY = "auth";
    /**
     * secret key.
     */
    @Value("${token.jwt.secretKey}")
    private String secretKey;

    /**
     * kid  and  k   for grafana
     */
    private String kid = "2391ecd4-3c16-4a54-9083-2269f556b5da";
    private String k = "Y4_Om2Jh-AW_5j6Jc87AffSgskxFWpSFXrFMC9Ju2GQ";
    /**
     * secret key byte array.
     */
    private byte[] secretKeyBytes;
    /**
     * Token validity time(seconds).
     */
    @Value("${token.jwt.tokenValidityInSeconds}")
    private long tokenValidityInSeconds;
    private JwtParser jwtParser;

    /**
     * init tokenValidityInSeconds and secretKey properties.
     */
    public String getSecretKey() {
        return secretKey;
    }

    /**
     * Create token.
     *
     * @param userName auth info
     * @return token
     */
    public String createToken(String userName) {
        long now = System.currentTimeMillis();
        Date validity;
        validity = new Date(now + this.getTokenValidityInSeconds() * 1000L);
        Claims claims = Jwts.claims().setSubject(userName);
        return Jwts.builder().setClaims(claims).setExpiration(validity)
                .signWith(Keys.hmacShaKeyFor(this.getSecretKeyBytes()), SignatureAlgorithm.HS256).compact();
    }

    /**
     * for grafana
     *
     * @param userName
     * @return
     */
    public String createGrafanaToken(String userName) {
        long now = System.currentTimeMillis();
        Date validity = new Date(now + this.getTokenValidityInSeconds() * 1000L);
        Claims claims = Jwts.claims().setSubject(userName);
        HashMap<String, Object> map = new HashMap<>();
        map.put("kid", kid);
        map.put("typ", "JWT");
        return Jwts.builder().setHeader(map).setClaims(claims).setExpiration(validity)
                .signWith(Keys.hmacShaKeyFor(Base64.decodeBase64(k)), SignatureAlgorithm.HS256).compact();
    }


    /**
     * validate token.
     *
     * @param token token
     */
    public void validateToken(String token) {
        if (jwtParser == null) {
            jwtParser = Jwts.parserBuilder().setSigningKey(this.getSecretKeyBytes()).build();
        }
        jwtParser.parseClaimsJws(token);
    }

    public byte[] getSecretKeyBytes() {
        if (secretKeyBytes == null) {
            try {
                secretKeyBytes = Decoders.BASE64.decode(secretKey);
            } catch (DecodingException e) {
                secretKeyBytes = secretKey.getBytes(StandardCharsets.UTF_8);
            }

        }
        return secretKeyBytes;
    }

    public long getTokenValidityInSeconds() {
        return tokenValidityInSeconds;
    }
}
